﻿#pragma once

#include "qlib/geo/label.h"

#include "qlib/geo/element.h"

namespace qlib {
enum struct GeoPartType;

class Pin;
using PinPtrArray = std::vector<std::shared_ptr<Pin>>;
using PinPtrArrayMap = std::unordered_map<Tag, PinPtrArray, Tag::Hash>;
// 0: 中心
using PinParts = std::tuple<Vec2d>;

enum struct PinType {
  B_Pin = 0,
  Q_Pin,
  Res_Pin,
  X_Pin,
  Z_Pin,
  P_Pin,
};

class QLIB_API Pin : public CellElementBase {
 public:
  Pin();
  Pin(std::string _text, Vec2d _origin, double _rotation = 0.0, double _magnification = 1.0, bool _x_reflection = false, uint32_t _layer = 0,
      uint32_t _datatype = 0);

  Pin(const Pin& oth);
  Pin& operator=(const Pin& other);

  using s_ptr = std::shared_ptr<Pin>;
  template <typename... Args>
  static s_ptr create(Args... args) {
    return std::make_shared<Pin>(args...);
  }
  // template <>
  static s_ptr create() {
    return std::make_shared<Pin>();
  }
  static s_ptr create(const Pin& value) { return std::make_shared<Pin>(value); }

  void copy(std::shared_ptr<Pin> pin);
  void copy(std::shared_ptr<Label> label);

  std::shared_ptr<Pin> copy() const;

  PinParts get_parts();
  Vec2dArray query_parts(GeoPartType type, uint32_t id);

  Vec2dArray bounding_box_origin();
  /**
   * @brief 获取此对象的包围盒
   * @details 根据标签位置和重复对象获取的极值数组，确定包围盒。若不重复，则返回[origin,origin]。
   * @return Vec2dArray 元素0为包围盒左下角，元素1为右上角
   */
  Vec2dArray bounding_box();
  Vec2dArray bounding_box_points() { return box_to_points(bounding_box()); };
  void apply_repetition(PinPtrArray& result);
  /**
   * @brief 变换标签
   *
   * @param[in] magnification 缩放倍率
   * @param[in] x_reflection  是否沿x轴镜像
   * @param[in] rotation      旋转角度
   * @param[in] origin        变换原点
   */
  void transform(double magnification, bool x_reflection, double rotation, const Vec2d origin);
  void rotate(double angle, Vec2d center);
  void translate(double dx, double dy);
  void mirror(qlib::Vec2d p0, qlib::Vec2d p1);

  void savePropertiesGDS() override;
  void loadPropertiesGDS() override;

  void savePropertiesOAS() override;
  void loadPropertiesOAS() override;

  Polygon::s_ptr to_polygon();
  std::vector<Polygon::s_ptr> to_polygons();

  Vec2dArray get_texts();
  Vec2dArray get_line();

  PinType getPinType();
  void setPinType(PinType type);

  uint32_t getId();
  void setId(uint32_t id);

  std::string getName();
  void setName(std::string name);

  double getRotation();
  void setRotation(double rotation);

  double fontSize = 0.5;
  double length{10.0};  ///< 引脚长度

  std::string text;          ///< 文本字符串
  Vec2d origin{0.0, 0.0};    ///< 标签的位置
  Anchor anchor{Anchor::O};  ///< 原点所在的方向

  double rotation{0.0};       ///< 旋转角度(弧度)
  double magnification{1.0};  ///< 放大率-比例因子
  bool x_reflection{false};   ///< 若为True，则标签在旋转前，将在水平轴上反射

  Vec2dArray box;
  bool is_display_type = true;
  bool is_display_name = true;
  bool is_display_id = true;
  Vec2dArray lines;  // 渲染缓存

  uint32_t layer{0};         ///< 标签的图层
  uint32_t datatype{0};      ///< 标签的类型
  PropertyArray properties;  ///< 属性对象
  Repetition repetition;     ///< 重复对象
};
}  // namespace qlib